package de.herberlin.contact;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.prefs.Preferences;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.border.TitledBorder;

/**
 * Executable UI class
 */
public class Main extends JFrame implements ActionListener, ProgressListener {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;
	
	/** The contact directory label. */
	private JLabel contactDirectoryLabel = new JLabel("...");
	
	/** The output file label. */
	private JLabel outputFileLabel = new JLabel("...");
	
	/** The contact directory button. */
	private JButton contactDirectoryButton = new JButton("Choose");
	
	/** The output file button. */
	private JButton outputFileButton = new JButton("Choose");

	/** The start button. */
	private JButton startButton = new JButton("Start");
	
	/** The progress bar. */
	private JProgressBar progressBar = new JProgressBar();

	/** The Constant KEY_CONTACT_DIR. */
	public static final String KEY_CONTACT_DIR = "contactDir";
	
	/** The Constant KEY_OUTPUT_FILE. */
	public static final String KEY_OUTPUT_FILE = "outputFile";

	/**
	 * Instantiates a new main.
	 */
	public Main() {
		super("Address Print");
		Manager.configureLogging();
		
		setDefaultValues();
		makeUi();
		addListener();
	}

	/**
	 * Adds listener to the buttons
	 */
	private void addListener() {
		contactDirectoryButton.addActionListener(this);
		outputFileButton.addActionListener(this);
		startButton.addActionListener(this);
	}

	/**
	 * Sets the default values for directory and output file.
	 */
	private void setDefaultValues() {
		Preferences prefs = Preferences.userNodeForPackage(getClass());
		contactDirectoryLabel.setText(prefs.get(KEY_CONTACT_DIR, System
				.getProperty("user.home")
				+ "\\Contacts"));
		outputFileLabel.setText(prefs.get(KEY_OUTPUT_FILE, System
				.getProperty("user.dir")
				+ "\\contact.txt"));
	}
	
	/**
	 * Sets a preference entry.
	 * 
	 * @param key the key
	 * @param value the value
	 */
	private void setPref(String key, String value) {
		Preferences.userNodeForPackage(getClass()).put(key, value);
	}

	/**
	 * Makes ui.
	 */
	private void makeUi() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLayout(new GridLayout(3, 1));

		// Contact directory
		JPanel p = new JPanel(new BorderLayout());
		p.setBorder(new TitledBorder("Contact Directory"));
		p.add(contactDirectoryLabel, BorderLayout.CENTER);
		p.add(contactDirectoryButton, BorderLayout.EAST);
		add(p);

		// output file
		p = new JPanel(new BorderLayout());
		p.setBorder(new TitledBorder("Output File"));
		p.add(outputFileLabel, BorderLayout.CENTER);
		p.add(outputFileButton, BorderLayout.EAST);
		add(p);

		// progressbar
		p = new JPanel(new BorderLayout());
		p.setBorder(new TitledBorder("Progress"));
		p.add(progressBar, BorderLayout.CENTER);
		p.add(startButton, BorderLayout.EAST);
		add(p);

		pack();

	}

	/**
	 * The main method.
	 * 
	 * @param args the args
	 */
	public static void main(String[] args) {
		new Main().setVisible(true);
	}

	/**
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		
		// choose Contact dirctory
		if (contactDirectoryButton.equals(e.getSource())) {
			JFileChooser chooser=new JFileChooser(contactDirectoryLabel.getText());
			chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			int result=chooser.showOpenDialog(this);
			if (result== JFileChooser.APPROVE_OPTION) {
				String txt=chooser.getSelectedFile().getAbsolutePath();
				contactDirectoryLabel.setText(txt);
				setPref(KEY_CONTACT_DIR, txt);
			}
			
		// choose output file
		} else if (outputFileButton.equals(e.getSource())) {
			JFileChooser chooser=new JFileChooser(new File(outputFileLabel.getText()).getParent());
			int result=chooser.showOpenDialog(this);
			if (result== JFileChooser.APPROVE_OPTION) {
				String txt=chooser.getSelectedFile().getAbsolutePath();
				outputFileLabel.setText(txt);
				setPref(KEY_OUTPUT_FILE, txt);
			}
			
		// start parser
		} else if (startButton.equals(e.getSource())) {
			start();
		
		// error
		} else {
			Manager.getLogger(this).log(Level.WARNING,
					"Unknown Action Source: " + e.getSource());
		}
	}

	
	/**
	 * Show error as JOption dialog
	 * 
	 * @param message the message
	 */
	private void showError(String message) {
		JOptionPane.showMessageDialog(this, message,"Error",JOptionPane.ERROR_MESSAGE);
	}
	
	/**
	 * Start the parser.
	 */
	private void start() {
		File contactDir=new File(contactDirectoryLabel.getText());
		if (!contactDir.exists() || !contactDir.isDirectory()) {
			showError(contactDir+"\nis not a directory.");
			return;
		}
		File outputFile=new File(outputFileLabel.getText());
		if (!outputFile.exists()) {
			try {
				outputFile.createNewFile();
			} catch (IOException e) {
				showError("Can't create file: \n"+outputFile);
				return;
			}
		} else if (!outputFile.canWrite()) {
			showError("Can't write to: \n"+outputFile);
			return;
		} else {
			int result=JOptionPane.showConfirmDialog(this, outputFile + "\nalready exists. Overwrite?");
			if (result == JOptionPane.OK_OPTION) {
				outputFile.delete();
				try {
					outputFile.createNewFile();
				} catch (IOException e) {
					showError("Can't create file: \n"+outputFile);
				}
			} else if (result == JOptionPane.NO_OPTION) {
				// append to existing file
			} else {
				return;
			}
			startButton.setEnabled(false);
			new Thread(new Runner(this,contactDir,outputFile)).start();
		}
	}

	/**
	 * Recieve progress events to set the progressbar.
	 * @see de.herberlin.contact.ProgressListener#progress(de.herberlin.contact.ProgressListener.ProgressEvent)
	 */
	@Override
	public void progress(ProgressEvent ev) {
		progressBar.setMaximum(ev.getTotal());
		progressBar.setValue(ev.getCurrent());
		if (ev.getTotal() == ev.getCurrent()) {
			startButton.setEnabled(true);
		}
	}
}
